package com.ff.xyh.access.service.impl.access;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ff.xyh.access.service.access.*;
import com.ff.xyh.common.entity.useraccess.*;
import com.ff.xyh.common.servicebase.exception.MyException;
import com.ff.xyh.common.utils.JwtUtils;
import com.ff.xyh.common.utils.MD5;
import com.ff.xyh.common.utils.CommonUtil;
import com.ff.xyh.common.qo.access.AccessUserQuery;
import com.ff.xyh.access.mapper.AccessUserMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 后台用户表 服务实现类
 * </p>
 *
 * @author ff
 * @since 2022-10-25
 */
@Service
public class AccessUserServiceImpl extends ServiceImpl<AccessUserMapper, AccessUser> implements AccessUserService {

    @Autowired
    AccessUserRoleService accessUserRoleService;

    @Autowired
    AccessRoleService accessRoleService;

    @Autowired
    AccessRolePermissionService accessRolePermissionService;

    @Autowired
    AccessPermissionService accessPermissionService;

    @Autowired
    RedisTemplate redisTemplate;



    @Override
    public String login(String userToken, String password) {
        //非空判断
        if(StringUtils.isEmpty(userToken) || StringUtils.isEmpty(password)) {
            throw new MyException(20001,"用户名或邮箱或密码为空，登录失败");
        }
        QueryWrapper<AccessUser> wrapper = new QueryWrapper<>();
        // 若包含 . 则为邮箱登录 后台系统不存在邮箱登录 所以是非法输入 若 userToken 为纯数字 则是手机号登录 若为数字加字母 则为用户名登录
        if (userToken.contains("."))
            throw new MyException(20001, "非法输入");
            // 不包含 . 且为纯数字 则是手机号登录
        else if (StringUtils.isNumeric(userToken))
            wrapper.eq("phone",userToken);
            // 不包含 . 也不是纯数字 则为用户名登录
        else
            wrapper.eq("username",userToken);

        AccessUser currentUser = baseMapper.selectOne(wrapper);

        if (currentUser == null) {
            throw new MyException(20001,"查无此人");
        }

        //判断密码 默认是 xyhroot
        //因为存储到数据库密码用MD5加密的
        //所以把输入的密码进行MD5加密，再和数据库密码进行比较
        if(! MD5.encrypt(password).equals(currentUser.getPassword())) {
            throw new MyException(20001,"密码错误");
        }
        //登录成功
        //生成token字符串，使用jwt工具类
        String jwtToken = JwtUtils.createJwtTokenWithUserId(currentUser.getId());
        return jwtToken;
    }

    @Override
    public List<AccessUser> getAllAccessUserWithPermissionId(String id) {
        QueryWrapper<AccessRolePermission> accessRolePermissionWrapper = new QueryWrapper<>();
        accessRolePermissionWrapper.eq("permission_id", id);
        List<AccessRolePermission> accessRolePermissionList = accessRolePermissionService.list(accessRolePermissionWrapper);
        if ( accessRolePermissionList == null || accessRolePermissionList.isEmpty()) {
            return null;
        } else {
//            通过permissionId得到所有roleId 再通过所有roleId遍历查询得到所有userId 然后将每一个roleId得到的user列表存入结果用户列表集中
            List<AccessUser> accessUserList = new ArrayList<>(); // 用于存放结果对象集
            Map mapRoleId = new HashMap<>();  // 用于通过roleId查询
            for (AccessRolePermission accessRolePermission : accessRolePermissionList) {
                mapRoleId.put("role_id", accessRolePermission.getRoleId());
                List<AccessUserRole> accessUserRoleList = accessUserRoleService.selectAccessUserRoleByMap(mapRoleId);
//                Map mapUserId = new HashMap<>();
//                for (AccessUserRole accessUserRole : accessUserRoleList) {
//                    mapUserId.put("user_id", accessUserRole.getUserId());
//                    List<AccessUser> list = baseMapper.selectByMap(mapRoleId);
//                    在list指定位置接上list
//                    accessUserList.addAll(accessUserList.size(), list);
//                }
                // userId在 accessUser表中是唯一的 所以不需要用list
                for (AccessUserRole accessUserRole : accessUserRoleList) {
                    AccessUser accessUser = baseMapper.selectById(accessUserRole.getUserId());
                    System.out.println("查询到用户：" + accessUser);
                    accessUserList.add(accessUser);
                }
                System.out.println("查询结果" + accessUserList);
            }
            return accessUserList;
        }

    }

    @Override
    public List<AccessUser> getAllAccessUserWithRoleId(String id) {
        QueryWrapper<AccessUserRole> accessUserRoleQueryWrapper = new QueryWrapper<>();
        accessUserRoleQueryWrapper.eq("role_id", id);
        List<AccessUserRole> accessUserRoleList = accessUserRoleService.list(accessUserRoleQueryWrapper);
        if ( accessUserRoleList == null || accessUserRoleList.isEmpty()) {
            return null;
        } else {
//            遍历accessUserRoleList 根据userId查询封装accessUserList
            List<AccessUser> accessUserList = new ArrayList<>(); // 用于存放结果对象集
            for (AccessUserRole accessUserRole : accessUserRoleList) {
                accessUserList.add(baseMapper.selectById(accessUserRole.getUserId()));
            }
            System.out.println("查询结果" + accessUserList);
            return accessUserList;
            }
        }

    @Override
    public AccessUser getAccessUserWithUserToken(String userToken) {
        //非空判断
        if(StringUtils.isEmpty(userToken)){
            throw null;
        }
        QueryWrapper<AccessUser> wrapper = new QueryWrapper<>();
        // 若符合手机号条件 则是手机号登录
        if (CommonUtil.isPhoneNumber(userToken))
             wrapper.eq("phone",userToken);
        // 若包含 . 则为邮箱登录 后台系统不存在邮箱登录 所以是非法输入
        else if (userToken.contains("."))
            throw new MyException(20001, "非法输入");
            // 不包含 . 也不是纯数字 则为用户名登录
        else if (StringUtils.isNumeric(userToken)) // 纯数字则是id登录
            wrapper.eq("id",userToken);
        else
            wrapper.eq("username",userToken);

        AccessUser accessUser = baseMapper.selectOne(wrapper);

        if (accessUser == null)
            return null;
         else
            return accessUser;
    }

    @Override
    public List<AccessUser> getUserListQuery(AccessUserQuery accessUserQuery) {
        Page<AccessUser> page = new Page<>(accessUserQuery.getCurrentPage(), accessUserQuery.getPageSize());
        List<AccessUser> resultList = new ArrayList<>();
        QueryWrapper<AccessUser> wrapper = new QueryWrapper<>();
        // 如果通过id查询 那就只需要查询id 然后直接封装返回
        if (!StringUtils.isEmpty(accessUserQuery.getUserId())) {
            AccessUser userGetById = this.getById(accessUserQuery.getUserId());
            resultList.add(userGetById);
            return resultList;
        }

        if (!StringUtils.isEmpty(accessUserQuery.getNicknameContains())) {
            wrapper.like("nickname", accessUserQuery.getNicknameContains());
        }
        if (!StringUtils.isEmpty(accessUserQuery.getPhone())) {
            wrapper.eq("phone", accessUserQuery.getPhone());
        }
        if (accessUserQuery.getSex() != null) {
            wrapper.eq("sex", accessUserQuery.getSex());
        }
        if (accessUserQuery.getGmtLastLogAfter() != null) {
            wrapper.ge("gmt_lastlog", accessUserQuery.getGmtLastLogAfter());
        }
        if (accessUserQuery.getGmtLastLogBefore() != null) {
            wrapper.le("gmt_lastlog", accessUserQuery.getGmtLastLogBefore());
        }

        IPage<AccessUser> resultPage = this.page(page, wrapper);

        resultList = resultPage.getRecords();

        return resultList;
    }

    @Override
    public Map<String, Object> getUserInfo(String token) {
        String userId = JwtUtils.getSubjectFromToken(token);
        Map<String, Object> result = new HashMap<>();
        AccessUser user = this.getById(userId);
        if (user == null) {
            return null;
        }
        List<String> roleNameList;
        //根据用户id获取角色
        List<AccessRole> roleList = accessRoleService.getRolesByUserId(user.getId());
        if (roleList == null || roleList.isEmpty()) {
            //前端框架必须返回一个角色，否则报错，如果没有角色，返回一个空角色
            roleNameList = new ArrayList<>();
            roleNameList.add("");
        } else {
            roleNameList = roleList.stream().map(item -> item.getRole()).collect(Collectors.toList());
            if(roleNameList == null || roleNameList.isEmpty()) {
                roleNameList.add("");
            }
        }

        //根据用户id获取操作权限值
        List<String> permissionValueList =
                accessPermissionService.selectPermissionValueListByUserId(user.getId());
//        redisTemplate.opsForValue().set("permissionValueList_" + userId, permissionValueList);
        /** 对应后台管理中的 src/store/modules/user.js */
        result.put("name", user.getNickname());
//        result.put("username", user.getUsername());
        result.put("avatar", user.getAvatar());
        result.put("roles", roleNameList);
//        result.put("roles", roleMarkList);
        result.put("permissionValueList", permissionValueList);
        return result;
    }


    @Override
    public boolean register(AccessUser accessUser) {
        if (! CommonUtil.isPhoneNumber(accessUser.getPhone())) {
            return false;
        }
//        accessUser.getUsername()
        QueryWrapper<AccessUser> wrapper = new QueryWrapper<>();
        wrapper.eq("username", accessUser.getUsername())
                .or()
                .eq("phone", accessUser.getPhone());
        if (this.getOne(wrapper) != null) {
            return false;
        }
        accessUser.setPassword(MD5.encrypt(accessUser.getPassword()));
        return this.save(accessUser);
    }

    @Override
    public boolean updatePassword(String userId, String rawPassword) {
        AccessUser accessUser = new AccessUser();
        accessUser.setId(userId).setPassword(MD5.encrypt(rawPassword));
        return baseMapper.updateById(accessUser) == 1;
    }

    @Override
    public boolean deleteAccessUserById(String userId) {
        return baseMapper.deleteById(userId) == 1;
    }
}
